/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.web;

import com.google.inject.Inject;
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;
import org.apache.commons.lang.StringUtils;
import org.xptracker.domain.Queue;
import org.xptracker.domain.SavedQuery;
import org.xptracker.domain.Timeline;
import org.xptracker.domain.User;
import org.xptracker.persistence.PersistenceManager;
import org.xptracker.services.auth.Authenticator;

import java.util.*;

@UrlBinding("/Profile.action")
public class ProfileActionBean extends StandardActionBean {
  private String PROFILE = "/profile.jsp";

  @SuppressWarnings({"UnusedDeclaration"})
  @Inject
  private Authenticator authenticator;

  private User user;
  private List<Queue> queues;
  private List<Timeline> timelines;

  public User getUser() { return user; }
  public void setUser(User user) { this.user = user; }

  public List<Queue> getQueues() { return queues; }
  public void setQueues(List<Queue> queues) { this.queues = queues; }

  public List<Timeline> getTimelines() { return timelines; }
  public void setTimelines(List<Timeline> timelines) { this.timelines = timelines; }

  public Authenticator getAuthenticator() { return authenticator; }

  @DefaultHandler
  public Resolution showProfile() {
    return new ForwardResolution(PROFILE);
  }

  @ValidationMethod
  public void validateNewPassword(ValidationErrors errors) {
    String password = param("_password");
    String confirm = param("_confirm");
    if (StringUtils.isNotBlank(password) && !password.equals(confirm)) {
      errors.add("_confirm", new SimpleError("Passwords do not match."));
    }
  }

  @HandlesEvent("DeleteQuery")
  public Resolution deleteQuery() {
    return persistenceManager.inTransaction(new PersistenceManager.UpdateHandler<Resolution>() {
      public Resolution doUpdate(PersistenceManager.UpdateReceiver receiver) {
        String queryId = param("queryId");
        User user = getCurrentUser();
        Iterator<SavedQuery> queriesI = user.getQueries().iterator();
        while (queriesI.hasNext()) {
          SavedQuery query = queriesI.next();
          if (queryId.equals(query.getId())) {
            queriesI.remove();
            user.getHomepageQueries().remove(query.getName());
            receiver.remove(query);
            getContext().getMessages().add(new SimpleMessage("Removed query ''{0}''", query.getName()));
          }
        }
        receiver.update(user);
        return new RedirectResolution(ProfileActionBean.class);
      }
    });
  }

  @HandlesEvent("Update")
  public Resolution update() {
    final User user = getUser();

    return persistenceManager.inTransaction(new PersistenceManager.UpdateHandler<Resolution>() {
      public Resolution doUpdate(PersistenceManager.UpdateReceiver receiver) {
        final User userToUpdate = currentUserProvider.getCurrentUser(true);
        if (authenticator.isPasswordManager()) {
          String password = param("_password");
          if (StringUtils.isNotBlank(password)) {
            userToUpdate.setPassword(password);
            getContext().getMessages().add(new SimpleMessage("Password changed."));
          }
        }
        userToUpdate.setTitle(user.getTitle());
        userToUpdate.setEmail(user.getEmail());
        userToUpdate.setFullName(user.getFullName());
        userToUpdate.setPhoneNumber(user.getPhoneNumber());
        userToUpdate.setBlogEntryLimit(user.getBlogEntryLimit());
        userToUpdate.setEmailMeMyChanges(user.getEmailMeMyChanges());

        final String[] queueIds = paramValues("queuePresent");
        List<Queue> queues = userToUpdate.getQueues();
        queues.clear();
        if (queueIds != null) {
          for (String queueId : queueIds) {
            Queue queue = loadEntity(Queue.class, queueId);
            queues.add(queue);
          }
        }

        final String[] queuesToTrack = paramValues("queueEmail");
        Set<String> queuesToTrackSet = new HashSet<String>();
        if (queuesToTrack != null) {
          queuesToTrackSet.addAll(Arrays.asList(queuesToTrack));
        }

        for(Queue queue: domain.listQueues(false)) {
          if (queuesToTrackSet.contains(queue.getId())) {
            queue.addTracker(getCurrentUser());
          } else {
            queue.removeTracker(getCurrentUser());
          }
          receiver.update(queue);
        }

        final String[] queryNames = paramValues("queryPresent");
        Set<String> queries = userToUpdate.getHomepageQueries();
        queries.clear();
        if (queryNames != null) {
          queries.addAll(Arrays.asList(queryNames));
        }

        final String[] timelineIds = paramValues("timelinePresent");
        List<Timeline> timelines = userToUpdate.getTimelines();
        timelines.clear();
        if (timelineIds != null) {
          for(String timelineId: timelineIds) {
            Timeline timeline = loadEntity(Timeline.class, timelineId);
            timelines.add(timeline);
          }
        }

        receiver.update(userToUpdate);
        getContext().getMessages().add(new SimpleMessage("User information updated."));
        return new RedirectResolution(ProfileActionBean.class);
      }
    });
  }

  @Before(stages=LifecycleStage.BindingAndValidation)
  public void provideData() {
    this.user = getCurrentUser();
    this.queues = domain.listQueues(false);
    this.timelines = domain.listTimelines();
  }
}
